package com.insurance.pingan.bid.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.insurance.common.constant.ConstantFlag;
import com.insurance.common.dto.BidBillEntityDto;
import com.insurance.common.dto.BidInvoiceEntityDto;
import com.insurance.common.dto.BidSubjectEntityDto;
import com.insurance.common.dto.ProposalCustomerEntityDto;
import com.insurance.entity.ProposalCustomerEntity;
import com.insurance.entity.ProposalEntity;
import com.insurance.pingan.bid.dto.accept.AcceptForFeeRequest;
import com.insurance.pingan.bid.dto.apply.*;
import com.insurance.pingan.bid.dto.download.DownLoadRequest;
import com.insurance.pingan.bid.dto.download.InvoiceContent;
import com.insurance.pingan.bid.dto.download.InvoiceRequest;
import com.insurance.pingan.bid.dto.download.PolicyContent;
import com.insurance.pingan.bid.dto.endorse.EndorseRequest;
import com.insurance.pingan.bid.dto.pay.PayRequestDto;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;

import static java.lang.System.in;
import static java.lang.System.out;

/**
 * @author Style
 * @version 1.0
 * @date 2020/10/25
 **/
public class PingAnBidRequestUtil {

    public static final String productCode = "MP05000038";

    public static final String planCode = "PL0500016";

    public static final String partnerName = "P_ZSRATB_GP";

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     * 组装获取平安投保请求对象
     *
     * @param bidSubjectEntity 标的对象
     * @param customerEntityList 投被保险人数组
     * @return
     * @throws Exception
     */
    public static BidApplyRequestDto convertPingAnApplyRequestData(BidSubjectEntityDto bidSubjectEntity,
                                List<ProposalCustomerEntity> customerEntityList) throws Exception{
        //流水号
        String transSerialNo = simpleDateFormat.format(new Date())+ IdUtil.fastSimpleUUID();
        //整体投保请求报文对象
        BidApplyRequestDto bidApplyRequestDto = new BidApplyRequestDto(createContract(bidSubjectEntity, customerEntityList),
                "21077", partnerName,
                transSerialNo, "APPLY", "210");
        return bidApplyRequestDto;
    }

    public static Contract createContract(BidSubjectEntityDto bidSubjectEntity, List<ProposalCustomerEntity> customerEntityList) throws Exception{
        Contract contract = new Contract();
        contract.setBaseInfo(createBaseInfo(bidSubjectEntity.getInsuranceEndTime()));
        contract.setApplicantInfoList(Arrays.asList(createApplicantInfo(customerEntityList.get(0))));
        contract.setBeneficaryInfoList(Arrays.asList(createApplicantInfo(customerEntityList.get(1))));
        contract.setExtendInfo(createExtendInfo());
        contract.setInsurantInfoList(contract.getApplicantInfoList());
        contract.setCompensationLimitInfoList(Arrays.asList(createCompensationLimitInfo()));
        contract.setRiskGroupInfoList(createRiskGroupInfoList(bidSubjectEntity));
        return contract;
    }

    public static List<JSONObject> createRiskGroupInfoList(BidSubjectEntityDto bidSubjectEntity){
        List<JSONObject> jsonList = new ArrayList<JSONObject>();
        JSONObject json = new JSONObject();
        List<RiskPropertyInfo> riskPropertyInfoList = createRiskPropertyInfoList(bidSubjectEntity);
        json.put("riskPropertyInfoList", JSONArray.fromObject(riskPropertyInfoList));
        json.put("planInfoList", JSONArray.fromObject(Arrays.asList(createPlanInfo())));
        jsonList.add(json);
        return jsonList;
    }

    public static BaseInfo createBaseInfo(String insuranceEndDate) throws Exception{
//        String currentTime = sdf.format(new Date()) + " 00:00:00";
//        Date afterDate = DateUtil.offset(dateFormat.parse(currentTime), DateField.DAY_OF_YEAR, 1);
        String currentTime = insuranceEndDate + " 00:00:00";
        Date currentDate = dateFormat.parse(currentTime);
        BaseInfo baseInfo = new BaseInfo(sdf.format(currentDate));
        baseInfo.setProductCode(productCode);
        return baseInfo;
    }

    public static ApplicantInfo createApplicantInfo(ProposalCustomerEntity proposalCustomerEntity){
        ApplicantInfo applicantInfo = new ApplicantInfo();
        applicantInfo.setAddress(proposalCustomerEntity.getAddress());
        applicantInfo.setCertificateNo(proposalCustomerEntity.getCardId());
        applicantInfo.setCertificateType(proposalCustomerEntity.getCardType());
//        applicantInfo.setInvoicePrintType("01");
        applicantInfo.setLinkManName(proposalCustomerEntity.getLinkManName());
        applicantInfo.setName(proposalCustomerEntity.getCustomerName());
        applicantInfo.setPersonnelType("0");
        applicantInfo.setOfficeTelephone(proposalCustomerEntity.getTelephoneNumber());
        return applicantInfo;
    }

    public static ExtendInfo createExtendInfo(){
        return new ExtendInfo("1");
    }

    public static PlanInfo createPlanInfo(){
        return new PlanInfo("1", planCode);
    }

    public static CompensationLimitInfo createCompensationLimitInfo(){
        CompensationLimitInfo compensationLimitInfo = new CompensationLimitInfo();
        compensationLimitInfo.setPlanCode(planCode);
        List<DutyAttributeInfo> dutyAttributeInfoList = Arrays.asList(new DutyAttributeInfo("16", "1000"),
                new DutyAttributeInfo("17", "1000"));
        compensationLimitInfo.setDutyAttributeInfoList(dutyAttributeInfoList);
        return compensationLimitInfo;
    }

    public static List<RiskPropertyInfo> createRiskPropertyInfoList(BidSubjectEntityDto bidSubjectEntity){
        RiskPropertyInfo riskPropertyInfo = new RiskPropertyInfo();
        riskPropertyInfo.setRiskPropertyMap(createRiskPropertyMap(bidSubjectEntity));
        return Arrays.asList(riskPropertyInfo);
    }

    public static RiskPropertyMap createRiskPropertyMap(BidSubjectEntityDto bidSubjectEntity){
        RiskPropertyMap riskPropertyMap = new RiskPropertyMap();
        riskPropertyMap.setAttr0(bidSubjectEntity.getProjectNumber());
        riskPropertyMap.setAttr1("中华人民共和国司法（港、澳、台除外）");
        riskPropertyMap.setAttr2(bidSubjectEntity.getCaseName());
        riskPropertyMap.setAttr3(bidSubjectEntity.getBiddingPerson());
        riskPropertyMap.setAttr4(bidSubjectEntity.getBiddingValidityTime());
        riskPropertyMap.setAttr5(bidSubjectEntity.getAgentCompany());
        riskPropertyMap.setAttr6(bidSubjectEntity.getBiddingProjectName());
        riskPropertyMap.setAttr7("1");
        riskPropertyMap.setAttr8(bidSubjectEntity.getAssureAmount());
        riskPropertyMap.setAttr9(bidSubjectEntity.getBidEndTime());
        riskPropertyMap.setAttr10(bidSubjectEntity.getProjectPredictAmount());
        riskPropertyMap.setAttr11(bidSubjectEntity.getAssureAmountEndTime());
//        riskPropertyMap.setAttr12(bidSubjectEntity.getBiddingSectionName());
        riskPropertyMap.setAttr12("1212");
        riskPropertyMap.setRate("1");
        riskPropertyMap.setTotalPayLimitation(bidSubjectEntity.getAssureAmount());
        return riskPropertyMap;
    }

    /**
     * 调用平安预支付接口
     *
     * @param callUrl 点击确认回调地址
     * @param proposalEntity 投保单对象
     * @param proposalCustomerEntity 投被保险人对象
     * @param bidSubjectEntity 标的对象
     * @return
     */
    public static PayRequestDto createPayRequestDto(String callUrl, ProposalEntity proposalEntity, ProposalCustomerEntity proposalCustomerEntity, BidSubjectEntityDto bidSubjectEntity){
        PayRequestDto payRequestDto = new PayRequestDto();
        payRequestDto.setTradeNo("ZsRa"+IdUtil.fastSimpleUUID().substring(4));
        payRequestDto.setProductName(bidSubjectEntity.getProductName());
        payRequestDto.setProductType("02");
        payRequestDto.setProductCode(productCode);
        payRequestDto.setCustomerName(proposalCustomerEntity.getCustomerName());
        payRequestDto.setReturnUrl("");
//        payRequestDto.setFrontNotifyUrl("http://39.98.148.165/insurance-bid/api/bid/"+bidSubjectEntity.getSubjectId()+"/acceptForFee");
//        payRequestDto.setFrontNotifyUrl("http://y3cke4.natappfree.cc/insurance-bid/api/bid/"+bidSubjectEntity.getSubjectId()+"/acceptForFee");
        payRequestDto.setFrontNotifyUrl(callUrl);
        payRequestDto.setApplyPolicyNo(bidSubjectEntity.getApplyPolicyNo());
        payRequestDto.setNoticeNo(bidSubjectEntity.getNoticeNo());
        payRequestDto.setPartnerName(partnerName);
        payRequestDto.setAmount(bidSubjectEntity.getTotalActualPremium());
        payRequestDto.setSignMsg(SHA256Util.sha256LowerCase(payRequestDto.getPartnerName()+payRequestDto.getProductCode()+payRequestDto.getCustomerName()+ payRequestDto.getAmount()+payRequestDto.getNoticeNo()));
        return payRequestDto;
    }

    /**
     * 校验获取平安投保响应内容
     *
     * {"ret":"0","msg":"","requestId":"bd17348b732a4a619d59290dfe7da85f","data":{
     * "responseCode":"999999",
     * "responseMsg":"成功"
     * ,"result":{
     *         "applyPolicyNo":"51077003900231426722",
     *         "policyNo":"",
     *         "noticeNo":"10150006000154770077",
     *         "totalInsuredAmount":"1000.00",
     *         "amountCurrencyCode":"01",
     *         "totalActualPremium":"500.00",
     *         "premiumCurrencyCode":"01",
     *         "insuranceBeginDate":"2020-10-26 00:00:00",
     *         "insuranceEndDate":"2021-01-01 23:59:59",
     *         "productName":"平安投标保证保险(平台)"
     * }
     * }}
     *
     * @param resultJsonStr 响应json字符串
     * @return
     */
    public static JSONObject pingAnApplyResultValidate(String resultJsonStr){
        JSONObject resultJson = new JSONObject();
        resultJson.put(ConstantFlag.CODE, ConstantFlag.ERROR);
        if(StringUtils.isBlank(resultJsonStr)){
            return resultJson;
        }
        JSONObject jsonObject = JSONObject.fromObject(resultJsonStr);
        //判断是否成功, 当ret为0的时候表示请求返回成功
        if(!jsonObject.containsKey("ret") || !"0".equals(jsonObject.getString("ret"))){
            return resultJson;
        }
        //获取内容
        JSONObject dataJson = jsonObject.getJSONObject("data");
        //判断是否投保成功, 当responseCode为999999的时候表示请求返回成功
        if(!dataJson.containsKey("responseCode") || !"999999".equals(dataJson.getString("responseCode"))){
            return resultJson;
        }
        JSONObject contentJson = dataJson.getJSONObject("result");
        contentJson.put(ConstantFlag.CODE, ConstantFlag.SUCCESS);
        return contentJson;
    }

    /**
     * 格式化平安支付返回报文
     *
     * {"ret":"0","msg":"","requestId":"rq111111111",
     * "data":"{"tradeNo":"ZsRa4a14b5ae4511ae0c4af0411aa2e4","resultCode":"SUCCESS",
     * "payUrl":"https://test-pipay.pingan.com/epcis_nps/tocpcpay.do?preId=ab1d7b57699c27ccab25d222f4b960a1&cpcNoticeNo=80200939271600334580",
     * "resultMsg":"下单成功"}"}
     *
     * @param payResultStr 平安支付返回报文字符串
     * @return
     */
    public static JSONObject pingAnPrePayFinanceResultValidate(String payResultStr){
        JSONObject resultJson = new JSONObject();
        resultJson.put(ConstantFlag.CODE, ConstantFlag.ERROR);
        if(StringUtils.isBlank(payResultStr)){
            return resultJson;
        }
        JSONObject jsonObject = JSONObject.fromObject(payResultStr);
        //判断是否成功, 当ret为0的时候表示请求返回成功
        if(!jsonObject.containsKey("ret") || !"0".equals(jsonObject.getString("ret"))){
            return resultJson;
        }
        //获取内容
        JSONObject contentJson = jsonObject.getJSONObject("data");
        contentJson.put(ConstantFlag.CODE, ConstantFlag.SUCCESS);
        return contentJson;
    }

    /**
     * 校验批改接口
     *
     * @param endorseStr 批改响应json
     * @return
     */
    public static JSONObject pingAnEndorseValidate (String endorseStr) {
        JSONObject resultJson = new JSONObject();
        resultJson.put(ConstantFlag.CODE, ConstantFlag.ERROR);
        if(StringUtils.isBlank(endorseStr)){
            return resultJson;
        }
        JSONObject jsonObject = JSONObject.fromObject(endorseStr);
        //判断是否成功, 当ret为0的时候表示请求返回成功
        if(!jsonObject.containsKey("ret") || !"0".equals(jsonObject.getString("ret"))){
            return resultJson;
        }
        JSONObject dataJsonObject = jsonObject.getJSONObject("data");
        if(!dataJsonObject.containsKey("responseCode") || !"9999".equals(dataJsonObject.getString("responseCode"))){
            return resultJson;
        }
        JSONObject contentJson = dataJsonObject.getJSONObject("result");
        contentJson.put(ConstantFlag.CODE, ConstantFlag.SUCCESS);
        return contentJson;
    }

    /**
     * 创建acceptForFee请求对象
     *
     * @param applyPolicyNo 应用保单号
     * @param transSerialNo 流水号
     * @return
     */
    public static AcceptForFeeRequest createAcceptForFeeRequest(String applyPolicyNo, String transSerialNo){
        AcceptForFeeRequest acceptForFeeRequest = new AcceptForFeeRequest();
        Contract contract = new Contract();
        BaseInfo baseInfo = new BaseInfo(productCode, applyPolicyNo);
        contract.setBaseInfo(baseInfo);
        acceptForFeeRequest.setContract(contract);
        acceptForFeeRequest.setPartnerName(partnerName);
        acceptForFeeRequest.setTransferCode("ACCEPT");
        acceptForFeeRequest.setTransSerialNo(simpleDateFormat.format(new Date())+NumberUtils.randomNumber(5));
        return acceptForFeeRequest;
    }

    /**
     * 校验投保查询
     *
     * @param payResultStr 支付响应json字符串
     * @return
     */
    public static JSONObject acceptForFeeValidate(String payResultStr){
        JSONObject resultJson = new JSONObject();
        resultJson.put(ConstantFlag.CODE, ConstantFlag.ERROR);
        if(StringUtils.isBlank(payResultStr)){
            return resultJson;
        }
        JSONObject jsonObject = JSONObject.fromObject(payResultStr);
        //判断是否成功, 当ret为0的时候表示请求返回成功
        if(!jsonObject.containsKey("ret") || !"0".equals(jsonObject.getString("ret"))){
            return resultJson;
        }
        //获取内容
        JSONObject contentJson = jsonObject.getJSONObject("data");
        if(contentJson.containsKey("responseCode") && "888888".equals(contentJson.getString("responseCode"))){
            contentJson = contentJson.getJSONObject("result");
            contentJson.put(ConstantFlag.CODE, ConstantFlag.SUCCESS);
        }else{
            return resultJson;
        }
        return contentJson;
    }

    /**
     * 调用平安电子发票, 获取电子保单字节数组
     *
     * @param printInvoiceStr
     * @return
     * @throws Exception
     */
    public static byte[] printInvoice(String printInvoiceStr) throws Exception{
        byte[] content = new byte[0];
        if(StringUtils.isBlank(printInvoiceStr)){
            return content;
        }
        JSONObject jsonObject = JSONObject.fromObject(printInvoiceStr);
        //判断是否成功, 当ret为0的时候表示请求返回成功
        if(!jsonObject.containsKey("ret") || !"0".equals(jsonObject.getString("ret"))){
            return content;
        }
        //表示成功
        if(jsonObject.getString("ret").equals("0")){
            JSONObject dataJson = jsonObject.getJSONArray("data").getJSONObject(0);
            if(dataJson.getString("resultCode").equals("999999") && dataJson.containsKey("invoiceValue")){
                String pdfBase64 = dataJson.getString("invoiceValue");
                content = Base64.getDecoder().decode(pdfBase64);
                return content;
            }else{
                throw new Exception("【调用平安电子发票接口异常】");
            }
        }else{
            throw new Exception("【调用平安电子发票接口异常, 返回错误】");
        }
    }

    /**
     * 创建下载电子保单请求
     *
     * @param bidSubjectEntityDto 标的对象
     * @return
     */
    public static DownLoadRequest createDownLoadRequest(BidSubjectEntityDto bidSubjectEntityDto){
        DownLoadRequest downLoadRequest = new DownLoadRequest();
        downLoadRequest.setApplyPolicyNo(bidSubjectEntityDto.getApplyPolicyNo());
        downLoadRequest.setPartnerCode(partnerName);
        downLoadRequest.setPolicyNo(bidSubjectEntityDto.getPolicyNo());
        downLoadRequest.setDocumentType("4");
        downLoadRequest.setIsElectronic("1");
        downLoadRequest.setLanguagePrint("0");
        downLoadRequest.setIsPrintAddrAndPost("1");
        downLoadRequest.setIsPrintInsurant("1");
        downLoadRequest.setSealTypeepas("0");
        downLoadRequest.setPaperTypeepas("1");
        downLoadRequest.setIsPrintClauseebcs("1");
        downLoadRequest.setIsCorporationSealebcs("0");
        downLoadRequest.setIsNeedEmployeeList("0");
        downLoadRequest.setFileType("0");
        return downLoadRequest;
    }

    /**
     * 创建发票请求对象
     *
     * @param policyNo 保单号
     * @param proposalCustomerEntityDto 投被保险人对象
     * @return
     */
    public static InvoiceRequest createInvoiceRequest(BidBillEntityDto bidBillEntityDto, String policyNo, ProposalCustomerEntityDto proposalCustomerEntityDto){
        InvoiceRequest invoiceRequest = new InvoiceRequest();
        invoiceRequest.setPartnerCode(partnerName);
        invoiceRequest.setAsynFlag("01");
        invoiceRequest.setIsCoinsuranceFlag("N");
        invoiceRequest.setInvoiceList(createInvoiceContentList(bidBillEntityDto, policyNo, proposalCustomerEntityDto));
        return invoiceRequest;
    }

    public static InvoiceContent createInvoiceContent(BidBillEntityDto bidBillEntityDto, String policyNo, ProposalCustomerEntityDto proposalCustomerEntityDto){
        InvoiceContent invoiceContent = new InvoiceContent();
        invoiceContent.setTransactionNo(simpleDateFormat.format(new Date())+IdUtil.fastSimpleUUID().substring(14));
        invoiceContent.setInvoiceCreater(partnerName);
        invoiceContent.setTaxPayerNO(bidBillEntityDto.getTaxPayerNo());
        invoiceContent.setInvoiceEmail(bidBillEntityDto.getInvoiceEmail());
        invoiceContent.setInvoiceOwner(bidBillEntityDto.getInvoiceOwner());
        invoiceContent.setInvoicePhone(bidBillEntityDto.getInvoicePhone());
        invoiceContent.setTaxPayerAddress(bidBillEntityDto.getTaxPayerAddress());
        invoiceContent.setTaxPayerBankAccount(bidBillEntityDto.getTaxPayerBankAccount());
        invoiceContent.setTaxPayerBankName(bidBillEntityDto.getTaxPayerBankName());
        invoiceContent.setTaxPayerTel(bidBillEntityDto.getTaxPayerTel());
        invoiceContent.setPolicyList(createPolicyContentList(policyNo, proposalCustomerEntityDto));
        return invoiceContent;
    }

    public static List<InvoiceContent> createInvoiceContentList(BidBillEntityDto bidBillEntityDto, String policyNo, ProposalCustomerEntityDto proposalCustomerEntityDto) {
        List<InvoiceContent> invoiceContentList = new ArrayList<InvoiceContent>();
        invoiceContentList.add(createInvoiceContent(bidBillEntityDto, policyNo, proposalCustomerEntityDto));
        return invoiceContentList;
    }

    public static PolicyContent createPolicyContent(String policyNo, ProposalCustomerEntityDto proposalCustomerEntityDto){
        PolicyContent policyContent = new PolicyContent();
        policyContent.setPolicyNo(policyNo);
        policyContent.setPersonnelName(proposalCustomerEntityDto.getCustomerName());
        policyContent.setCertificateType("99");
        policyContent.setCertificateNo(proposalCustomerEntityDto.getCardId());
        return policyContent;
    }

    public static List<PolicyContent> createPolicyContentList(String policyNo,ProposalCustomerEntityDto proposalCustomerEntityDto){
        List<PolicyContent> policyContentList = new ArrayList<PolicyContent>();
        policyContentList.add(createPolicyContent(policyNo, proposalCustomerEntityDto));
        return policyContentList;
    }

    /**
     * 创建批改接口请求对象
     *
     * @param bidSubjectEntityDto 标的对象
     * @param applicationCustomerEntityDto 投保人对象
     * @param insuredCustomerEntityDto 被保险人对象
     * @return
     */
    public static EndorseRequest createEndorseRequest(BidSubjectEntityDto bidSubjectEntityDto, ProposalCustomerEntityDto applicationCustomerEntityDto, ProposalCustomerEntityDto insuredCustomerEntityDto){
        EndorseRequest endorseRequest = new EndorseRequest();
        //批改场景
        endorseRequest.setEdrSceneCode("90001");
        //数据来源，固定填ICORE-PTS
        endorseRequest.setDataSource("ICORE-PTS");
        //批改人
        endorseRequest.setUpdatedBy(partnerName);
        //合作伙伴编码
        endorseRequest.setPartnerCode(partnerName);

        Contract contract = new Contract();

        BaseInfo baseInfo = new BaseInfo(bidSubjectEntityDto.getPolicyNo(), null, null);
        contract.setBaseInfo(baseInfo);

        //投保人信息
        ApplicantInfo applicantInfo = new ApplicantInfo();
        applicantInfo.setName(applicationCustomerEntityDto.getCustomerName());
        applicantInfo.setAddress(applicationCustomerEntityDto.getAddress());
        applicantInfo.setMobileTelephone(applicationCustomerEntityDto.getTelephoneNumber());
        contract.setApplicantInfoList(Arrays.asList(applicantInfo));

        //被保人列表
        ApplicantInfo insuredInfo = new ApplicantInfo();
        insuredInfo.setName(insuredCustomerEntityDto.getCustomerName());
        contract.setInsurantInfoList(Arrays.asList(insuredInfo));

        //标的信息
        RiskPropertyMap riskPropertyMap = new RiskPropertyMap();
        //招标项目标包编号
        riskPropertyMap.setAttr0(bidSubjectEntityDto.getProjectNumber());
        //招标人
        riskPropertyMap.setAttr3(bidSubjectEntityDto.getBiddingPerson());
        //招标项目名称
        riskPropertyMap.setAttr6(bidSubjectEntityDto.getBiddingProjectName());
        //投标截止日
        riskPropertyMap.setAttr9(bidSubjectEntityDto.getBidEndTime());
        //招标项目预估合同金额
        riskPropertyMap.setAttr10(bidSubjectEntityDto.getProjectPredictAmount());

        //标的列表
        List<RiskPropertyMap> riskPropertyInfoList = Arrays.asList(riskPropertyMap);

        JSONObject json = new JSONObject();
        json.put("riskPropertyInfoList", JSONArray.fromObject(riskPropertyInfoList));
        contract.setRiskGroupInfoList(Arrays.asList(json));

        //单证信息
        endorseRequest.setContract(contract);

        return endorseRequest;
    }

}
